package com.fujin.gulimall.search.thread;

import org.springframework.cache.annotation.Cacheable;

import java.util.concurrent.*;

/**
 * @title: ThreadTest
 * @Author uIn
 * @Date: 2022/2/21 16:20
 * @Version 1.0
 */
public class ThreadTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /**
         * 1、继承Thread接口
         *      thread01 thread01 = new thread01();
         *      thread01.start();
         * 2、实现Runnable
         *      new Thread(new runnable01()).start();
         * 3、实现Callable
         *      FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
         *      new Thread(futureTask).start();
         * 4、线程池（）
         *      除线程池以上的三种，在实际业务中不考虑使用
         *      4.1、创建
         *          1、使用Executors工具类
         *          2、new ThreadPoolExecutor()
         *
         *      4.2、ThreadPoolExecutor()线程池创建七大参数
         *          corePoolSize：核心线程数，一创建线程池就有几个线程负责执行任务
         *          maximumPoolSize:最大线程数量；控制资源
         *          keepAliveTime:存活时间，如果当前线程大于核心线程数量，除核心线程外的线程空闲超过
         *                          keepAliveTime这个时间就会将核心线程之外的线程释放掉
         *          unit:时间单位
         *          BlockingQueue<Runnable> workQueue:阻塞队列，如果任务很多就会将目前多出来的任务
         *                                              放入队列中，只要有线程空闲了就会到队列中拿到任务执行
         *          ThreadFactory threadFactory:线程的创建工厂
         *          RejectedExecutionHandler handler:如果队列满了，就会按照指定的拒绝策略拒绝执行任务
         *
         *      4.3、线程池工作流程:
         *          1、当核心线程满了，就将再进来的任务放入阻塞队列中，空闲下来的核心线程就去队列中获取任务执行
         *          2、当阻塞队列满了，就直接开启新的线程执行，最大只能开到指定的最大线程数
         *          3、最大线程数满了之后，就使用拒绝策略拒绝任务
         *          4、最大线程数开启的任务执行完了之后，就会有很多空闲的线程，除了核心线程外的线程只要超过了
         *          指定的超时时间就会被释放掉
         *
         * 总结:
         *      1、继承Thread接口、实现Runnable都没有返回值
         *      2、实现Runnable、实现Callable不能控制资源
         *      3、使用线程池可以控制资源
         */

//        Executors.newCachedThreadPool();   核心线程是0，所有都可回收
//        Executors.newFixedThreadPool(); 固定大小，核心线程和最大线程数是一样的
//        Executors.newScheduledThreadPool(); 具有定时功能的线程池
//        Executors.newSingleThreadExecutor();    单线程的线程池，后台从队列里面获取任务，逐个执行
        System.out.println("业务start");
        FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());

        new Thread(futureTask).start();

        //获取返回值，这样是阻塞线程 因为需要等待获取到结果
        Integer integer = futureTask.get();
        System.out.println("业务end");
    }

    public static class thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("任务执行开始!!!");
            int i = 10 / 2;
            System.out.println("任务执行结束!!!");
        }
    }

    public static class runnable01 implements Runnable{

        @Override
        public void run() {
            System.out.println("任务执行开始!!!");
            int i = 10 / 2;
            System.out.println("任务执行结束!!!");
        }
    }

    public static class Callable01 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("任务执行开始!!!");
            int i = 10 / 2;
            System.out.println("任务执行结束!!!");
            return i;
        }
    }

}
